/**
 *    Copyright (C) 2008, 2009  Victor Smirnov <aist11@gmail.com>
 *
 *    This program is free software; you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation; either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License along
 *    with this program; if not, write to the Free Software Foundation, Inc.,
 *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 *    See LICENSE.exceptions in the root folder of this project for possible
 *    exceptions
 *
 */

#ifndef _CUBEFS_CORE_CONTAINER_BUILDER_HPP
#define	_CUBEFS_CORE_CONTAINER_BUILDER_HPP

#include <cubefs/core/tools/reflection.hpp>
#include <cubefs/core/tools/types/typelist.hpp>
#include <cubefs/core/tools/types/list_printer.hpp>

#include <cubefs/core/container/type_locator.hpp>
#include <cubefs/core/container/profile.hpp>

namespace cubefs    {
namespace ctr       {


using cubefs::TypeList;
using namespace cubefs::tools;

template <
    typename List,
    template <typename, typename> class Element,
    typename Base
>
struct Builder;


template <
    typename T1,
    typename T2,
    template <typename, typename> class Element,
    typename Base
>
struct Builder<TypeList<T1, T2>, Element, Base>:
            public Element<
                        T1,
                        Builder<
                            T2,
                            Element,
                            Base
                        >
            >
{

private:
    typedef Element<
				T1,
				Builder<
					T2,
					Element,
					Base
				>
			>                                                  				BaseType;

public:
    
    Builder(): BaseType() {}
};

template <
    typename T,
    template <typename, typename> class Element,
    typename Base
>
struct Builder<TypeList<T, NullType>, Element, Base>: public Element<T, Base> {
private:
    typedef Element<T, Base>	                 							BaseType;

public:
    Builder(): BaseType() {}
};


template <
    template <typename, typename> class Element,
    typename Base
>
struct Builder<NullType, Element, Base>: public Base {
private:
    typedef Base                                                            BaseType;

public:
    Builder(): BaseType() {}
};






//------------------------------------------------------------------------------
//Self Type Aware Type Builder
//------------------------------------------------------------------------------

template <
    typename List,
    template <typename, typename, typename> class Element,
    typename MyType,
    typename Base
>
struct TypeAwareBuilder;


template <
    typename Head,
    typename Tail,
    template <typename, typename, typename> class Element,
    typename MyType,
    typename Base
>
struct TypeAwareBuilder<TypeList<Head, Tail>, Element, MyType, Base>:
                public Element<
                        Head,
                        MyType,
                        TypeAwareBuilder<
                            Tail,
                            Element,
                            MyType,
                            Base
                        >
                > {
private:
    typedef Element<
                        Head,
                        MyType,
                        TypeAwareBuilder<
                            Tail,
                            Element,
                            MyType,
                            Base
                        >
            >                                                  				BaseType;
public:
    TypeAwareBuilder(MyType &me): BaseType(me) {}

};

template <
    typename Head,
    template <typename, typename, typename> class Element,
    typename MyType,
    typename Base
>
struct TypeAwareBuilder<
            TypeList<Head, NullType>,
            Element,
            MyType,
            Base
       >: public Element<Head, MyType, Base> {
private:
    typedef Element<Head, MyType, Base>      								BaseType;
    
public:
    
    TypeAwareBuilder(MyType &me): BaseType(me) {}
};



template <
    template <typename, typename, typename> class Element,
    typename MyType,
    typename Base
>
struct TypeAwareBuilder<
            NullType,
            Element,
            MyType,
            Base>: public Base {
private:
    typedef Base                                                                BaseType;

public:

    TypeAwareBuilder(MyType &me): BaseType(me) {}

};

}
}

#endif
